home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1997 February / macformat-047.iso / Shareware Plus / Developers / PlayerPRO 4.5.3 Dev.Kit / Plug-Ins / Music Import⁄Export Plugs / S3M2Mad.c < prev   
Encoding:
Text File  |  1996-10-29  |  29.5 KB  |  1,143 lines  |  [TEXT/CWIE]

  1. /********************                        ***********************/
  2. //
  3. //    Player PRO 4.5x -- S3M to MADx
  4. //
  5. //    Version 2.0    - 12.3.95 ANR
  6. //
  7. //    To use with CodeWarrior 68K or PPC
  8. //
  9. //    Antoine ROSSET
  10. //    16 Tranchees
  11. //    1206 GENEVA
  12. //    SWITZERLAND
  13. //    
  14. //    FAX:            (+41 22) 346 11 97
  15. //    Compuserve:    100277,164
  16. //    Internet:         rosset@dial.eunet.ch
  17. //
  18. /********************                        ***********************/
  19.  
  20. #include "S3M.h"
  21. #include "MAD.h"
  22. #include "RDriver.h"
  23.  
  24. #if defined(powerc) || defined(__powerc)
  25. enum {
  26.         PlayerPROPlug = kCStackBased
  27.         | RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
  28.         | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof( OSType)))
  29.         | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof( Ptr*)))
  30.         | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof( MADPartition*)))
  31.         | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof( PPInfoRec*)))
  32.         | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof( MADDriverSettings*)))
  33. };
  34.  
  35. ProcInfoType __procinfo = PlayerPROPlug;
  36. #else
  37. #include <A4Stuff.h>
  38. #endif
  39.  
  40. #define LOW(para) ((para) & 15)
  41. #define HI(para) ((para) >> 4)
  42.  
  43. unsigned long Tdecode32( void *msg_buf)
  44. {
  45.   unsigned char *buf = msg_buf;
  46.   
  47.   return( (unsigned long) buf[3] << 24) | ( (unsigned long) buf[2] << 16) | ( (unsigned long) buf[ 1] << 8) | ( (unsigned long) buf[0]);
  48. }
  49.  
  50. short Tdecode16( void *msg_buf)
  51. {
  52.   unsigned char *buf = msg_buf;
  53.   
  54.   return ( (short) buf[1] << 8) | ( (short) buf[0]);
  55. }
  56.  
  57. Cmd* GetMADCommand( register short PosX, register short    TrackIdX, register PatData*    tempMusicPat)
  58. {
  59.     if( PosX < 0) PosX = 0;
  60.     else if( PosX >= tempMusicPat->header.size) PosX = tempMusicPat->header.size -1;
  61.         
  62.     return( & (tempMusicPat->Cmds[ (tempMusicPat->header.size * TrackIdX) + PosX]));
  63. }
  64.  
  65. Ptr MADNewPtr( long size, MADDriverSettings* init)
  66. {
  67.     if( init->sysMemory) return NewPtrSys( size);
  68.     else return NewPtr( size);
  69. }
  70.  
  71. Ptr MADNewPtrClear( long size, MADDriverSettings* init)
  72. {
  73.     if( init->sysMemory) return NewPtrSysClear( size);
  74.     else return NewPtrClear( size);
  75. }
  76.  
  77. void pStrcpy(register unsigned char *s1, register unsigned char *s2)
  78. {
  79.     register short len, i;
  80.     
  81.     len = *s2;
  82.     for ( i = 0; i <= len; i++) s1[ i] = s2[ i];
  83. }
  84.  
  85. void strncpy( Ptr dst, Ptr str, long size)
  86. {
  87.     BlockMove( str, dst, size);
  88. }
  89.  
  90. void mystrcpy( Ptr a, Ptr b)
  91. {
  92.     BlockMove( b + 1, a, b[ 0]);
  93. }
  94.  
  95. void ConvertS3MEffect( Byte B0, Byte B1, Byte *Cmd, Byte *Arg)
  96. {
  97.     Str255    tStr;
  98.     Byte        LoB1 = LOW( B1);
  99.     Byte        HiB1 = HI( B1);
  100.     
  101.     switch( B0 + 0x40)
  102.     {
  103.         default:    *Cmd = 0;            *Arg = 0;        break;
  104.         // Speed
  105.         case 'A':    *Cmd = speedE;        *Arg = B1;    break;
  106.         // Tempo
  107.         case 'T':    *Cmd = speedE;        *Arg = B1;    break;
  108.  
  109.         case 'B':    *Cmd = fastskipE;        *Arg = B1;    break;
  110.  
  111.         case 'C':    *Cmd = skipE;            *Arg = B1;    break;
  112.  
  113.         case 'D':
  114.             if( LoB1 == 0 || HiB1 == 0)        // Slide volume
  115.             {
  116.                 *Cmd = slidevolE;        *Arg = B1;
  117.             }
  118.             else if( HiB1 == 0x0F)        // Fine Slide volume DOWN
  119.             {
  120.                 *Cmd = extendedE;
  121.                 *Arg = 11 << 4;
  122.                 *Arg += LoB1;
  123.             }
  124.             else if( LoB1 == 0x0F)        // Fine Slide volume UP
  125.             {
  126.                 *Cmd = extendedE;
  127.                 *Arg = 10 << 4;
  128.                 *Arg += HiB1;
  129.             }
  130.         break;
  131.         
  132.         case 'E':
  133.             if( HiB1 == 0x0F)        // FineSlide DOWN
  134.             {
  135.                 *Cmd = extendedE;
  136.                 *Arg = 2 << 4;        //not supported
  137.                 *Arg += LoB1;
  138.             }
  139.             else if( HiB1 == 0x0E)    // ExtraFineSlide DOWN
  140.             {
  141.                 *Cmd = 0;            *Arg = 0;        //not supported
  142.             }
  143.             else                    // Slide DOWN
  144.             {
  145.                 *Cmd = upslideE;        *Arg = B1;
  146.             }
  147.         break;
  148.  
  149.         case 'F':
  150.             if( HiB1 == 0x0F)        // FineSlide UP
  151.             {
  152.                 *Cmd = extendedE;
  153.                 *Arg = 1 << 4;        //not supported
  154.                 *Arg += LoB1;
  155.             }
  156.             else if( HiB1 == 0x0E)    // ExtraFineSlide UP
  157.             {
  158.                 *Cmd = 0;            *Arg = 0;        //not supported
  159.             }
  160.             else                    // Slide UP
  161.             {
  162.                 *Cmd = downslideE;        *Arg = B1;
  163.             }
  164.         break;
  165.  
  166.         case 'G':    *Cmd = portamentoE;    *Arg = B1;    break;
  167.         case 'H':    *Cmd = vibratoE;        *Arg = B1;    break;
  168.         
  169.         case 'J':    *Cmd = arpeggioE;        *Arg = B1;    break;
  170.         case 'K':    *Cmd = vibratoslideE;    *Arg = B1;    break;
  171.         case 'L':    *Cmd = portaslideE;        *Arg = B1;    break;
  172.         case 'O':    *Cmd = offsetE;        *Arg = B1;    break;
  173.  
  174.         case 'S':        // Special Effects
  175.             switch( HiB1)
  176.             {
  177.                 default:    *Cmd = 0;        *Arg = 0;                            break;
  178.                 case 2:    *Cmd = extendedE;    *Arg = 5 << 4;        *Arg += LoB1;        break;    // FineTune
  179.                 case 3:    *Cmd = extendedE;    *Arg = 4 << 4;        *Arg += LoB1;        break;    // Set Vibrato WaveForm
  180.                 case 4:    *Cmd = extendedE;    *Arg = 7 << 4;        *Arg += LoB1;        break;    // Set Tremolo WaveForm
  181.                 case 0xB:    *Cmd = extendedE;    *Arg = 6 << 4;        *Arg += LoB1;        break;    // Loop pattern
  182.                 case 0xC:    *Cmd = extendedE;    *Arg = 12 << 4;    *Arg += LoB1;        break;    // Cut sample
  183.                 case 0xD:    *Cmd = extendedE;    *Arg = 13 << 4;    *Arg += LoB1;        break;    // Delay sample
  184.                 case 0xE:    *Cmd = extendedE;    *Arg = 14 << 4;    *Arg += LoB1;        break;    // Delay pattern
  185.             }
  186.         break;
  187.     }
  188. }
  189.  
  190. void ConvertMADEffect( Byte Cmd, Byte Arg, Byte *B0, Byte *B1)
  191. {
  192.     *B0 = 0;
  193.     *B1 = 0;
  194.  
  195.     switch( Cmd)
  196.     {
  197.         case speedE:        *B0 = 'A' - 0x40;    *B1 = Arg;    break;
  198.         case fastskipE:        *B0 = 'B' - 0x40;    *B1 = Arg;    break;
  199.         case skipE:        *B0 = 'C' - 0x40;    *B1 = Arg;    break;
  200.         case slidevolE:        *B0 = 'D' - 0x40;    *B1 = Arg;    break;
  201.         case upslideE:        *B0 = 'E' - 0x40;    *B1 = Arg;    break;
  202.         case downslideE:    *B0 = 'F' - 0x40;    *B1 = Arg;    break;
  203.         case portamentoE:    *B0 = 'G' - 0x40;    *B1 = Arg;    break;
  204.         case vibratoE:        *B0 = 'H' - 0x40;    *B1 = Arg;    break;
  205.         
  206.         case arpeggioE:        *B0 = 'J' - 0x40;    *B1 = Arg;    break;
  207.         case vibratoslideE:    *B0 = 'K' - 0x40;    *B1 = Arg;    break;
  208.         case portaslideE:    *B0 = 'L' - 0x40;    *B1 = Arg;    break;
  209.         case offsetE:        *B0 = 'O' - 0x40;    *B1 = Arg;    break;
  210.         
  211.         case extendedE:
  212.             switch( (Arg & 0xF0) >> 4)
  213.             {
  214.                 case 1:    *B0 = 'F' - 0x40;    *B1 = 0xf0 + (Arg & 0x0F);        break;
  215.                 case 2:    *B0 = 'E' - 0x40;    *B1 = 0xf0 + (Arg & 0x0F);        break;
  216.                 
  217.                 case 5:    *B0 = 'S' - 0x40;    *B1 = 0x20 + (Arg & 0x0F);        break;
  218.                 
  219.                 case 4:    *B0 = 'S' - 0x40;    *B1 = 0x30 + (Arg & 0x0F);        break;
  220.                 case 7:    *B0 = 'S' - 0x40;    *B1 = 0x40 + (Arg & 0x0F);        break;
  221.                 case 6:    *B0 = 'S' - 0x40;    *B1 = 0xb0 + (Arg & 0x0F);        break;
  222.                 case 12:    *B0 = 'S' - 0x40;    *B1 = 0xc0 + (Arg & 0x0F);        break;
  223.                 case 13:    *B0 = 'S' - 0x40;    *B1 = 0xd0 + (Arg & 0x0F);        break;
  224.                 case 14:    *B0 = 'S' - 0x40;    *B1 = 0xe0 + (Arg & 0x0F);        break;
  225.                 
  226.                 case 11:    *B0 = 'D' - 0x40;    *B1 = 0xf0 + (Arg & 0x0F);        break;
  227.                 case 10:    *B0 = 'D' - 0x40;    *B1 = 0x0f + ((Arg & 0x0F)<<4);    break;
  228.             }
  229.         break;
  230.     }
  231. }
  232.  
  233. Ptr    ConvertMad2S3M( MADPartition *theMAD, MADDriverSettings *init)
  234. {
  235.     long                 i, x, z, maxInstru;
  236.     Ptr                finalS3M, finalS3MCopy, maxfinalS3M;
  237.     long                InstruSize;
  238.     long                NoIns;
  239.     long                genHeaderSize;
  240.     s3minsform        *ins[ 64];
  241.     Cmd                *aCmd;
  242.     long                PatternSize;
  243.     
  244.     s3mform            *s3minfo;
  245.     
  246.     unsigned short        *parapins;
  247.     unsigned short        *parappat;
  248.     
  249.     /********************************/
  250.     /*             MAD INFORMATIONS               */
  251.     /********************************/
  252.     InstruSize = 0;
  253.     PatternSize = 0;
  254.     NoIns = 0;
  255.     for( i = 0; i < 64 ; i++)
  256.     {
  257.         if( theMAD->header->fid[ i].numSamples > 0)
  258.         {
  259.             InstruSize            += 16 + theMAD->sample[ i][ 0]->size;
  260.             //NoIns++;
  261.             
  262.             NoIns = i+1;
  263.         }
  264.     }
  265.     
  266.     for( i = 0; i < theMAD->header->numPat;i++)
  267.     {
  268.         PatternSize += 6L * theMAD->header->numChn * theMAD->partition[ i]->header.size;
  269.         PatternSize += 16;
  270.     }
  271.     /********************************/
  272.     
  273.     
  274.     finalS3MCopy = finalS3M = MADNewPtr(         sizeof( s3mform) +
  275.                                         theMAD->header->numPointers +
  276.                                         NoIns*2 +
  277.                                         theMAD->header->numPat*2 +
  278.                                         sizeof(s3minsform) * NoIns +
  279.                                         InstruSize + 
  280.                                         PatternSize, init);
  281.     maxfinalS3M = finalS3M + GetPtrSize( finalS3M);
  282.     if( finalS3M == 0L) return 0L;
  283.     
  284.     
  285.     
  286.     
  287.     /********************************/
  288.     /* s3minfo -- s3minfo -- s3minfo -- s3minfo -- */
  289.     /********************************/
  290.     {
  291.         s3minfo = (s3mform*) finalS3MCopy;
  292.     
  293.         strncpy( s3minfo->name, theMAD->header->name, 28);
  294.         s3minfo->sig1             = 26;
  295.         s3minfo->type            = 16;
  296.         s3minfo->sig2[ 0] = s3minfo->sig2[ 1] = 0;
  297.         
  298.         s3minfo->ordernum        =    theMAD->header->numPointers;        s3minfo->ordernum = Tdecode16(  &s3minfo->ordernum);
  299.         s3minfo->insnum        =     NoIns;                            s3minfo->insnum = Tdecode16(  &s3minfo->insnum);
  300.         s3minfo->patnum        =    theMAD->header->numPat;            s3minfo->patnum = Tdecode16(  &s3minfo->patnum);
  301.         
  302.         s3minfo->flags            =    0;
  303.         s3minfo->cwtv            =    0x2013;
  304.         s3minfo->ffv            =    0;                                s3minfo->ffv = Tdecode16(  &s3minfo->ffv);
  305.         
  306.         
  307.         strncpy( s3minfo->s3msig, "SCRM", 4);
  308.         
  309.         s3minfo->mastervol        =     64;
  310.         s3minfo->initialspeed    =    theMAD->header->speed;
  311.         s3minfo->initialtempo    =    theMAD->header->tempo;
  312.         s3minfo->mastermul        =    0x30;
  313.         
  314.         for( i = 0; i < 12; i++) s3minfo->sig3[ i] = 0;
  315.         
  316.         for( i = 0; i < theMAD->header->numChn; i++) s3minfo->chanset[ i] = i;
  317.         for( i = theMAD->header->numChn; i < 32; i++) s3minfo->chanset[ i] = 255;
  318.         
  319.         finalS3MCopy += 96;
  320.     }
  321.     if( finalS3MCopy >= maxfinalS3M) Debugger();
  322.     
  323.     /********************************/
  324.     /*     orders -- orders -- orders -- orders      */
  325.     /********************************/
  326.     {
  327.         unsigned char    *orders;
  328.         
  329.         orders = (unsigned char *) finalS3MCopy;
  330.         for( i = 0; i < theMAD->header->numPointers; i++)
  331.         {
  332.             orders[ i] = theMAD->header->oPointers[ i];        orders[ i] = Tdecode16(  &orders[ i]);
  333.         }
  334.         finalS3MCopy += theMAD->header->numPointers;
  335.     }
  336.     if( finalS3MCopy >= maxfinalS3M) Debugger();
  337.     /********************************/
  338.     /*     Ins Num -- Ins Num -- Ins Num -- Ins Num      */
  339.     /********************************/
  340.     {
  341.         parapins = (unsigned short *) finalS3MCopy;
  342.         
  343.         for( i = 0; i < NoIns; i++) parapins[ i] = 0;
  344.         finalS3MCopy += NoIns*2L;
  345.     }
  346.     if( finalS3MCopy >= maxfinalS3M) Debugger();
  347.     /********************************/
  348.     /*     Pat Num -- Pat Num -- Pat Num -- Pat Num */
  349.     /********************************/
  350.     {
  351.         parappat = (unsigned short *) finalS3MCopy;
  352.         
  353.         for( i = 0; i < theMAD->header->numPat; i++) parappat[ i] = 0;
  354.         finalS3MCopy += theMAD->header->numPat*2L;
  355.     }
  356.     if( finalS3MCopy >= maxfinalS3M) Debugger();
  357.     
  358.     /*********************************/
  359.     /*     Ins Form -- Ins Form -- Ins Form -- Ins Form */
  360.     /*********************************/
  361.     for (i = 0; i < NoIns; i++)
  362.     {
  363.         if( theMAD->header->fid[ i].numSamples > 0)
  364.         {
  365.             sData        *curData = theMAD->sample[ i][ 0];
  366.             
  367.             parapins[ i] =  (16L + finalS3MCopy - finalS3M) / 16L;
  368.             finalS3MCopy = finalS3M + parapins[ i]*16L;
  369.             parapins[ i] = Tdecode16(  ¶pins[ i]);
  370.             
  371.             /**/
  372.             
  373.             ins[ i] = (s3minsform*) finalS3MCopy;
  374.             
  375.             ins[ i]->instype                =    1;
  376.             strncpy( (Ptr) ins[ i]->insdosname, theMAD->header->fid[i].name, 12);
  377.             ins[ i]->memsegh            =    0;
  378.             ins[ i]->memsegl            =    0;
  379.             ins[ i]->inslength            =    curData->size;                        ins[ i]->inslength = Tdecode32( &ins[ i]->inslength);
  380.             ins[ i]->insloopbeg            =    curData->loopBeg;                    ins[ i]->insloopbeg = Tdecode32( &ins[ i]->insloopbeg);
  381.             ins[ i]->insloopend            =    curData->loopBeg + curData->loopSize;    ins[ i]->insloopend = Tdecode32( &ins[ i]->insloopend);
  382.             ins[ i]->insvol                =    curData->vol;
  383.             ins[ i]->insdsk                =    0;
  384.             ins[ i]->inspack                =    0;
  385.             
  386.             ins[ i]->insflags            =     0;
  387.             if( curData->loopSize != 0)     ins[ i]->insflags += 1;
  388.             if( curData->amp == 16)         ins[ i]->insflags += 4;
  389.             
  390.             ins[ i]->c2spd                =    curData->c2spd;                    ins[ i]->c2spd = Tdecode32(  &ins[ i]->c2spd);
  391.             for( x = 0; x < 4; x++)        ins[ i]->inssig2[ x] = 0;
  392.             ins[ i]->insgvspos            =    256;                                ins[ i]->insgvspos = Tdecode16(  &ins[ i]->insgvspos);
  393.             ins[ i]->insint512            =    0;                                ins[ i]->insint512 = Tdecode16(  &ins[ i]->insint512);
  394.             ins[ i]->insintlastused        =    0;
  395.             strncpy( (Ptr) ins[ i]->insname, theMAD->header->fid[i].name, 28);
  396.             ins[ i]->inssig                =    'SCRS';
  397.         }
  398.         else
  399.         {
  400.             parapins[ i] =  (16L + finalS3MCopy - finalS3M) / 16L;
  401.             finalS3MCopy = finalS3M + parapins[ i]*16L;
  402.             parapins[ i] = Tdecode16(  ¶pins[ i]);
  403.             
  404.             /**/
  405.             
  406.             ins[ i] = (s3minsform*) finalS3MCopy;
  407.             
  408.             ins[ i]->instype                =    0;
  409.             strncpy( (Ptr) ins[ i]->insdosname, theMAD->header->fid[i].name, 12);
  410.             ins[ i]->memsegh            =    0;
  411.             ins[ i]->memsegl            =    0;
  412.             ins[ i]->inslength            =    0;
  413.             ins[ i]->insloopbeg            =    0;
  414.             ins[ i]->insloopend            =    0;
  415.             ins[ i]->insvol                =    0;
  416.             ins[ i]->insdsk                =    0;
  417.             ins[ i]->inspack                =    0;
  418.             
  419.             ins[ i]->insflags            =     0;
  420.             
  421.             ins[ i]->c2spd                =    NOFINETUNE;                        ins[ i]->c2spd = Tdecode32(  &ins[ i]->c2spd);
  422.             for( x = 0; x < 4; x++)        ins[ i]->inssig2[ x] = 0;
  423.             ins[ i]->insgvspos            =    256;    
  424.             ins[ i]->insint512            =    0;
  425.             ins[ i]->insintlastused        =    0;
  426.             strncpy( (Ptr) ins[ i]->insname, theMAD->header->fid[i].name, 28);
  427.             ins[ i]->inssig                =    0;
  428.         }
  429.         /**/
  430.         
  431.         finalS3MCopy += sizeof(s3minsform);
  432.     }
  433.     if( finalS3MCopy >= maxfinalS3M) Debugger();
  434.     /*********************************/
  435.     /*     Sample Data -- Sample Data -- Sample Data   */
  436.     /*********************************/
  437.     
  438.     for (i = 0; i < NoIns; i++)
  439.     {
  440.         if( theMAD->header->fid[ i].numSamples > 0)
  441.         {
  442.             sData        *curData = theMAD->sample[ i][ 0];
  443.             long            tempL;
  444.             
  445.             tempL = (16L + finalS3MCopy - finalS3M) / 16L;
  446.             
  447.             ins[ i]->memsegl = tempL & 0x0000FFFF;
  448.             ins[ i]->memsegl = Tdecode16(  &ins[ i]->memsegl);
  449.             
  450.             ins[ i]->memsegh = (long) (tempL &0x00FF0000)>>16L;
  451.             
  452.             finalS3MCopy = finalS3M + tempL*16L;
  453.             
  454.             BlockMove( curData->data, finalS3MCopy, curData->size);
  455.             
  456.             if( curData->amp == 8)
  457.             {
  458.                 for( tempL = 0; tempL < curData->size; tempL++) *(finalS3MCopy + tempL) += 0x80;
  459.             }
  460.             
  461.             finalS3MCopy += curData->size;
  462.         }
  463.     }
  464.     if( finalS3MCopy >= maxfinalS3M) Debugger();
  465.     /*********************************/
  466.     /*     Pattern Data -- Pattern Data -- Pattern Data */
  467.     /*********************************/
  468.     
  469.     for (i = 0; i < theMAD->header->numPat; i++)
  470.     {
  471.         long        Row = 0;
  472.         short        *sizePtr;
  473.     
  474.         parappat[ i] = (16L + finalS3MCopy - finalS3M) / 16L;
  475.         finalS3MCopy = finalS3M + parappat[ i]*16L;
  476.         parappat[ i] = Tdecode16(  ¶ppat[ i]);
  477.         
  478.         sizePtr = (short*) finalS3MCopy;
  479.         
  480.         finalS3MCopy++;
  481.         finalS3MCopy++;        // A short is 2 bytes...
  482.         
  483.         while( Row < 64)
  484.         {
  485.             for( z = 0; z < theMAD->header->numChn; z++)
  486.             {
  487.                 Byte        *tempChar = (Byte*) finalS3MCopy;
  488.                 
  489.                 aCmd = GetMADCommand( Row, z, theMAD->partition[ i]);
  490.                 
  491.                 if(        aCmd->note        != 0xFF ||
  492.                             aCmd->ins            != 0 ||
  493.                             aCmd->cmd            != 0 ||
  494.                             aCmd->arg            != 0 ||
  495.                             aCmd->vol            != 0xFF)
  496.                     {
  497.                 //        *tempChar = 0;
  498.                         
  499.                         finalS3MCopy++;
  500.                         
  501.                         // Channel
  502.                         
  503.                         *tempChar    = z;
  504.                         
  505.                         // PERIOD
  506.                         
  507.                         if( aCmd->note != 0xFF || aCmd->ins != 0)
  508.                         {
  509.                             short Octave, Note;
  510.                         
  511.                             *tempChar += 32;
  512.                             
  513.                             if( aCmd->note == 0xFF)
  514.                             {
  515.                                 finalS3MCopy[ 0] = 0xFF;
  516.                             }
  517.                             else
  518.                             {
  519.                                 short curNote;
  520.                                 
  521.                                 if( aCmd->ins != 0) curNote = aCmd->note + theMAD->sample[ aCmd->ins-1][ 0]->relNote;
  522.                                 else curNote = aCmd->note;
  523.                                 
  524.                                 Octave = curNote / 12;
  525.                                 Note = curNote - Octave*12;
  526.                                 
  527.                                 finalS3MCopy[ 0] = Octave << 4;
  528.                                 finalS3MCopy[ 0] += Note;
  529.                             }
  530.                             
  531.                             finalS3MCopy[ 1] = aCmd->ins;
  532.                             finalS3MCopy += 2L;
  533.                         }
  534.                         
  535.                         // VOLUME
  536.                         
  537.                         if( aCmd->vol != 0xFF || aCmd->cmd == volumeE)
  538.                         {
  539.                             *tempChar += 64;
  540.                             
  541.                             if( aCmd->cmd == volumeE) finalS3MCopy[ 0] = aCmd->arg;
  542.                             else finalS3MCopy[ 0] = aCmd->vol - 0x10;
  543.                             
  544.                             finalS3MCopy += 1L;
  545.                         }
  546.                         
  547.                         // PARAMETER
  548.                         
  549.                         if( aCmd->cmd != 0 || aCmd->arg != 0)
  550.                         {
  551.                             *tempChar += 128;
  552.                             
  553.                             ConvertMADEffect( aCmd->cmd, aCmd->arg, (Byte*) &finalS3MCopy[ 0], (Byte*) &finalS3MCopy[ 1]);
  554.                             
  555.                             finalS3MCopy += 2L;
  556.                         }
  557.                     }
  558.             }
  559.             
  560.             *finalS3MCopy = 0;    // end of row
  561.             finalS3MCopy++;
  562.             Row++;
  563.         }
  564.         
  565.         *sizePtr = finalS3MCopy - (Ptr) sizePtr;
  566.         *sizePtr -= 2;
  567.         *sizePtr = Tdecode16(  sizePtr);
  568.         
  569.         if( finalS3MCopy >= maxfinalS3M) Debugger();
  570.     }
  571.     
  572.     SetPtrSize( finalS3M, finalS3MCopy - finalS3M);
  573.     
  574.     return( (Ptr) finalS3M);
  575. }
  576.  
  577. OSErr ConvertS3M2Mad( Ptr    theS3M, long MODSize, MADPartition *theMAD, MADDriverSettings *init)
  578. {
  579.     long                 i, PatMax, x, z, channel, Row;
  580.     long                 sndSize, OffSetToSample, OldTicks, starting;
  581.     Ptr                MaxPtr;
  582.     OSErr            theErr;
  583.     Ptr                theInstrument[ 64], destPtr;
  584.     Byte                tempChar, *theS3MCopy;
  585.     short            Note, Octave, maxTrack;
  586.     short            S3Mperiod[ 12] = {1712,1616,1524,1440,1356,1280,1208,1140,1076,1016, 960, 907};
  587.     long                note_st3period;
  588.     long                note_amigaperiod;
  589.     Byte                *ChannelSettings;
  590.     
  591.     /**** Variables pour le MAD ****/
  592.     Cmd                *aCmd;
  593.  
  594.     /**** Variables pour le S3M ****/
  595.     
  596.     s3mform            s3minfo;
  597.     /********************************/
  598.  
  599.     for( i = 0 ; i < 64; i ++)
  600.     {
  601.         theInstrument[ i] = 0L;
  602.     }
  603.  
  604.     /**** Header principal *****/
  605.     theS3MCopy = (Byte*) theS3M;
  606.     
  607.     if( sizeof( s3minfo) < 96) Debugger();        // Just a test..
  608.     
  609.     BlockMove( theS3MCopy, &s3minfo, 96);
  610.     theS3MCopy += 96;
  611.     
  612.     s3minfo.ordernum    = Tdecode16(  &s3minfo.ordernum);
  613.     s3minfo.insnum        = Tdecode16(  &s3minfo.insnum);
  614.     s3minfo.patnum        = Tdecode16(  &s3minfo.patnum);
  615.     s3minfo.flags        = Tdecode16(  &s3minfo.flags);
  616.     s3minfo.cwtv        = Tdecode16(  &s3minfo.cwtv);
  617.     s3minfo.ffv        = Tdecode16(  &s3minfo.ffv);
  618.  
  619.     /**** Order Num *****/
  620.     s3minfo.orders = (unsigned char *) MADNewPtr( s3minfo.ordernum, init);
  621.     if( s3minfo.orders == 0L) return MADNeedMemory;
  622.     BlockMove( theS3MCopy, s3minfo.orders, s3minfo.ordernum);
  623.     theS3MCopy += s3minfo.ordernum;
  624.     
  625.     /**** Ins Num *****/
  626.     s3minfo.parapins = (unsigned short *) MADNewPtr( s3minfo.insnum * 2L, init);
  627.     if( s3minfo.parapins == 0L) return MADNeedMemory;
  628.     BlockMove( theS3MCopy, s3minfo.parapins, s3minfo.insnum * 2L);
  629.     theS3MCopy += s3minfo.insnum * 2L;
  630.     for( i = 0; i < s3minfo.insnum; i++)
  631.     {
  632.         s3minfo.parapins[ i] = Tdecode16(  &s3minfo.parapins[ i]);
  633.     }
  634.     
  635.     
  636.     /**** Pat Num *****/
  637.     s3minfo.parappat = (unsigned short *) MADNewPtr( s3minfo.patnum * 2L, init);
  638.     if( s3minfo.parappat == 0L) return MADNeedMemory;
  639.     BlockMove( theS3MCopy, s3minfo.parappat, s3minfo.patnum * 2L);
  640.     theS3MCopy += s3minfo.patnum * 2L;
  641.     for( i = 0; i < s3minfo.patnum; i++)
  642.     {
  643.         s3minfo.parappat[ i] = Tdecode16(  &s3minfo.parappat[ i]);
  644.     }
  645.  
  646.     /**** Ins Data ****/
  647.     if( s3minfo.insnum > 64) s3minfo.insnum = 64;
  648.     s3minfo.insdata = (s3minsform *) MADNewPtr( sizeof(s3minsform) * s3minfo.insnum, init);
  649.     if( s3minfo.insdata == 0L) return MADNeedMemory;
  650.     for (i = 0; i < s3minfo.insnum; i++)
  651.     {
  652.         theInstrument[ i] = 0L;
  653.     
  654.         theS3MCopy = (Byte*) theS3M;
  655.         theS3MCopy += s3minfo.parapins[i]*16L;
  656.         
  657.         BlockMove( theS3MCopy, &s3minfo.insdata[i], sizeof(s3minsform));
  658.         
  659.         s3minfo.insdata[i].memsegl        = Tdecode16( &s3minfo.insdata[i].memsegl);
  660.         s3minfo.insdata[i].inslength        = Tdecode32( &s3minfo.insdata[i].inslength);
  661.         
  662.         if( s3minfo.insdata[i].insflags&1)
  663.         {
  664.             s3minfo.insdata[i].insloopbeg        = Tdecode32( &s3minfo.insdata[i].insloopbeg);
  665.             s3minfo.insdata[i].insloopend        = Tdecode32( &s3minfo.insdata[i].insloopend);
  666.         }
  667.         else
  668.         {
  669.             s3minfo.insdata[i].insloopbeg        = 0;
  670.             s3minfo.insdata[i].insloopend        = 0;
  671.         }
  672.         
  673.         s3minfo.insdata[i].c2spd            = Tdecode32(  &s3minfo.insdata[i].c2spd);
  674.         s3minfo.insdata[i].insgvspos        = Tdecode16(  &s3minfo.insdata[i].insgvspos);
  675.         s3minfo.insdata[i].insint512        = Tdecode16(  &s3minfo.insdata[i].insint512);
  676.         s3minfo.insdata[i].insintlastused    = Tdecode32( &s3minfo.insdata[i].insintlastused);
  677.         
  678.         if (s3minfo.insdata[i].instype == 1 && s3minfo.insdata[i].inspack == 0 && s3minfo.insdata[i].inssig == 'SCRS')
  679.             {
  680.                 long tempL;
  681.             
  682.                 theS3MCopy = (Byte*) theS3M;
  683.                 
  684.             tempL = (((long)s3minfo.insdata[i].memsegh)<<16|s3minfo.insdata[i].memsegl)<<4;
  685.                 
  686.                 theS3MCopy += tempL;
  687.                 
  688.                 theInstrument[ i] = (Ptr) theS3MCopy;
  689.             }
  690.             else
  691.             {
  692.                 theInstrument[ i] = 0L;
  693.             }
  694.     }
  695.  
  696.     /******** Le S3M a été lu et analysé ***********/
  697.     /******** Copie des informations dans le MAD ***/
  698.     
  699.     theMAD->header = (MADSpec*) MADNewPtrClear( sizeof( MADSpec), init);
  700.     if( theMAD->header == 0L) return MADNeedMemory;
  701.         
  702.     theMAD->header->MAD = 'MADH';
  703.     for(i=0; i<32; i++) theMAD->header->name[i] = 0;
  704.     for(i=0; i<28; i++) theMAD->header->name[i] = s3minfo.name[i];
  705.     
  706.     mystrcpy( theMAD->header->infos, (Ptr) "\pConverted by PlayerPRO S3M Plug (©Antoine ROSSET <rosset@dial.eunet.ch>)");
  707.     
  708.     theMAD->header->numPat        = s3minfo.patnum;
  709.     theMAD->header->numPointers    = s3minfo.ordernum;
  710.     theMAD->header->speed        = s3minfo.initialspeed;
  711.     theMAD->header->tempo        = s3minfo.initialtempo;
  712.     
  713.     for(i=0; i<128; i++) theMAD->header->oPointers[ i] = 0;
  714.     for(i=0; i<s3minfo.ordernum; i++)
  715.     {
  716.         theMAD->header->oPointers[ i] = s3minfo.orders[i];
  717.         
  718.         if( theMAD->header->oPointers[ i] < 0 || theMAD->header->oPointers[ i] >= s3minfo.patnum) theMAD->header->oPointers[ i] = 0;
  719.     }
  720.  
  721.     /********************/
  722.     /***** INSTRUMENTS *****/
  723.     /********************/
  724.  
  725.     for(i  = 0 ; i < MAXINSTRU; i++)
  726.     {
  727.         for( x = 0; x < MAXSAMPLE; x++) theMAD->sample[ i][ x] = 0L;
  728.  
  729.         theMAD->header->fid[i].numSamples    = 0;
  730.     }
  731.  
  732.     for(i=0; i<s3minfo.insnum; i++)
  733.     {
  734.         InstrData        *curIns = &theMAD->header->fid[ i];
  735.         
  736.         curIns->type    = 0;
  737.         
  738.         if( theInstrument[ i] != 0L)
  739.         {
  740.             sData    *curData;
  741.  
  742.             curIns->numSamples = 1;
  743.             curIns->volFade = DEFAULT_VOLFADE;
  744.  
  745.             curData = theMAD->sample[ i][ 0] = (sData*) MADNewPtrClear( sizeof( sData), init);
  746.             if( curData == 0L) return MADNeedMemory;
  747.             
  748.             curData->size        = s3minfo.insdata[i].inslength;
  749.             curData->loopBeg     = s3minfo.insdata[i].insloopbeg;
  750.             curData->loopSize     = s3minfo.insdata[i].insloopend - s3minfo.insdata[i].insloopbeg;
  751.             curData->vol        = s3minfo.insdata[i].insvol;
  752.             curData->c2spd        = s3minfo.insdata[i].c2spd;
  753.             curData->loopType    = 0;
  754.             curData->amp        = 8;        if( s3minfo.insdata[i].insflags&4)    curData->amp        = 16;
  755.             curData->panning    = 0;
  756.             curData->relNote    = 0;
  757.             for( x = 0; x < 28; x++) theMAD->header->fid[i].name[x] = s3minfo.insdata[i].insname[x];
  758.             
  759.             curData->data         = MADNewPtr( curData->size, init);
  760.             if( curData->data == 0L) return MADNeedMemory;
  761.             
  762.             if( curData->data == 0L) DebugStr("\pInstruments: I NEED MEMORY !!! NOW !");
  763.             
  764.             if( curData->data != 0L)
  765.             {
  766.                 BlockMove( theInstrument[i], curData->data, curData->size);
  767.                 
  768.                 if( s3minfo.ffv != 1)
  769.                 {
  770.                     long temp;
  771.                     
  772.                     for( temp = 0; temp < curData->size; temp++) *(curData->data + temp) -= 0x80;
  773.                 }
  774.             }
  775.         }
  776.         else curIns->numSamples = 0;
  777.     }
  778.     /********************/
  779.     
  780.     /*********************/
  781.     /*           Check MaxTrack         */
  782.     /*********************/
  783.     
  784.     maxTrack = 0;
  785.     for(i=0;i<32;i++)
  786.     {
  787.         if(s3minfo.chanset[ i]<16) maxTrack++;
  788.     }
  789.     maxTrack++;
  790.     maxTrack /= 2;
  791.     maxTrack *= 2;
  792.     
  793. /*    maxTrack = 0;
  794.     for( i = 0; i < theMAD->header->numPat ; i++)
  795.     {
  796.         Row = 0;
  797.         
  798.         if( s3minfo.parappat[ i] > 0)
  799.         {
  800.             theS3MCopy = (Byte*) theS3M;
  801.             theS3MCopy += ( (long) s3minfo.parappat[i] )*16L;
  802.             theS3MCopy++;
  803.             
  804.             while( Row < 64)
  805.             {
  806.                 tempChar = *theS3MCopy;
  807.                 theS3MCopy++;
  808.                 
  809.                 if( tempChar == 0) Row++;
  810.                 else
  811.                 {    // Channel
  812.                     channel = tempChar;
  813.                     channel &= 31;
  814.                     
  815.                     if( channel > maxTrack) maxTrack = channel;
  816.                     if( (tempChar & 32) != 0) theS3MCopy += 2L;
  817.                     if( (tempChar & 64) != 0) theS3MCopy += 1L;
  818.                     if( (tempChar & 128) != 0) theS3MCopy += 2L;
  819.                 }
  820.             }
  821.         }
  822.     }
  823.     maxTrack ++;
  824.     
  825.     
  826.     // ** Pair **
  827.     maxTrack++;
  828.     maxTrack /= 2;
  829.     maxTrack *= 2;*/
  830.     /********************/
  831.     /***** TEMPORAIRE ******/
  832.     /********************/
  833.     
  834.     theMAD->header->numChn = maxTrack;
  835.     
  836.     starting = 0;
  837.  
  838.     for( i = 0; i < MAXPATTERN; i++) theMAD->partition[ i] = 0L;
  839.     for( i = 0; i < theMAD->header->numPat ; i++)
  840.     {
  841.         theMAD->partition[ i] = (PatData*) MADNewPtrClear( sizeof( PatData) + theMAD->header->numChn * 64L * sizeof( Cmd), init);
  842.         if( theMAD->partition[ i] == 0L) return MADNeedMemory;
  843.         
  844.         theMAD->partition[ i]->header.size = 64L;
  845.         theMAD->partition[ i]->header.compMode = 'NONE';
  846.         
  847.         for( x = 0; x < 20; x++) theMAD->partition[ i]->header.name[ x] = 0;
  848.     
  849.         theMAD->partition[ i]->header.patBytes = 0L;
  850.         theMAD->partition[ i]->header.unused2 = 0L;
  851.     
  852.         MaxPtr = (Ptr) theMAD->partition[ i];
  853.         MaxPtr += sizeof( PatData) + theMAD->header->numChn * 64L * sizeof( Cmd);
  854.         
  855.         for( Row = 0; Row < 64; Row++)
  856.         {
  857.             for(z = 0; z < theMAD->header->numChn; z++)
  858.             {
  859.                 aCmd = GetMADCommand( Row, z, theMAD->partition[ i]);
  860.                 
  861.                 aCmd->note        = 0xFF;
  862.                 aCmd->ins            = 0;
  863.                 aCmd->cmd        = 0;
  864.                 aCmd->arg        = 0;
  865.                 aCmd->vol        = 0xFF;
  866.             }
  867.         }
  868.         
  869.         if( s3minfo.parappat[ i] > 0)
  870.         {
  871.             theS3MCopy = (Byte*) theS3M;
  872.             theS3MCopy += ( (long) s3minfo.parappat[i] )*16L;
  873.             theS3MCopy++;
  874.             theS3MCopy++;
  875.             
  876.             Row = 0;
  877.             while( Row < 64)
  878.             {
  879.                 /*
  880.                     BYTE:flag,     0        =    end of row
  881.                                 &31        =    channel
  882.                                 &32        =    follows;  BYTE:note, BYTE:instrument
  883.                                 &64        =    follows;  BYTE:volume
  884.                                 &128    =    follows; BYTE:command, BYTE:info
  885.                 */
  886.                     
  887.                     tempChar = *theS3MCopy;
  888.                     theS3MCopy++;
  889.     
  890.                     if( tempChar == 0) Row++;
  891.                     else
  892.                     {
  893.                         // Channel
  894.                         
  895.                         channel = tempChar;
  896.                         channel &= 31;
  897.                         if( channel >= 0 && channel < theMAD->header->numChn) aCmd = GetMADCommand( Row, channel, theMAD->partition[ i]);
  898.                         else aCmd = 0L;
  899.                         
  900.                         // PERIOD
  901.                         
  902.                         if( (tempChar & 32) != 0)
  903.                         {
  904.                             if( aCmd != 0L)
  905.                             {
  906.                                 aCmd->note = theS3MCopy[ 0];
  907.                                 
  908.                                 Octave = (aCmd->note & 0xF0) >> 4;
  909.                                 Note = (aCmd->note & 0x0F);
  910.                                     
  911.                                 aCmd->note = Octave*12 + Note;
  912.                                 if( aCmd->note < 0 || aCmd->note >= NUMBER_NOTES) aCmd->note = 0xFF;
  913.                                 
  914.                                 aCmd->ins = theS3MCopy[ 1];
  915.                             }
  916.                             theS3MCopy += 2L;
  917.                         }
  918.                         
  919.                         // VOLUME
  920.                         
  921.                         if( (tempChar & 64) != 0)
  922.                         {
  923.                             if( aCmd != 0L)
  924.                             {
  925.                                 aCmd->vol = theS3MCopy[ 0];
  926.                                 if( aCmd->vol > 64) aCmd->vol = 64;
  927.                                 aCmd->vol += 0x10;
  928.                             }
  929.                             theS3MCopy += 1L;
  930.                         }
  931.                         else aCmd->vol = 255;
  932.                         
  933.                         // PARAMETER
  934.                         
  935.                         if( (tempChar & 128) != 0)
  936.                         {
  937.                             if( aCmd != 0L)
  938.                             {
  939.                                 if( theS3MCopy[ 0] != 255)
  940.                                 {
  941.                                     ConvertS3MEffect( theS3MCopy[ 0], theS3MCopy[ 1], &aCmd->cmd, &aCmd->arg);
  942.                                 }
  943.                             }
  944.                             theS3MCopy += 2L;
  945.                         }
  946.                     }
  947.             }
  948.         }
  949.     }
  950.     
  951.     DisposPtr( (Ptr) s3minfo.orders);        DisposPtr( (Ptr) s3minfo.parapins);
  952.     DisposPtr( (Ptr) s3minfo.parappat);        DisposPtr( (Ptr) s3minfo.insdata);
  953.  
  954.     return noErr;
  955. }
  956.  
  957. OSErr ExtractS3MInfo( PPInfoRec *info, Ptr AlienFile)
  958. {
  959.     s3mform        *myS3M = ( s3mform*) AlienFile;
  960.     short        i;
  961.     short        maxInstru;
  962.     short        tracksNo;
  963.     s3mform        s3minfo;
  964.     /********************************/
  965.  
  966.     /**** Header principal *****/
  967.     BlockMove( AlienFile, &s3minfo, 96);
  968.     
  969.     /*** Signature ***/
  970.     
  971.     info->signature = 'S3M ';
  972.     
  973.     /*** Internal name ***/
  974.     
  975.     myS3M->name[ 27] = '\0';
  976.     pStrcpy( info->internalFileName, CtoPstr( myS3M->name));
  977.  
  978.     /*** Total Patterns ***/
  979.     
  980.     info->totalPatterns = Tdecode16(  &s3minfo.patnum);
  981.     
  982.     /*** Partition Length ***/
  983.     
  984.     info->partitionLength = Tdecode16( &s3minfo.ordernum);
  985.     
  986.     /*** Total Instruments ***/
  987.     
  988.     info->totalInstruments = Tdecode16(  &s3minfo.insnum);
  989.     
  990.     pStrcpy( info->formatDescription, "\pS3M Plug");
  991.  
  992.     return noErr;
  993. }
  994.  
  995. OSErr TestS3MFile( Ptr AlienFile)
  996. {
  997. s3mform    *myS3M = ( s3mform*) AlienFile;
  998.  
  999. if(    myS3M->s3msig[ 0] == 'S' &&
  1000.     myS3M->s3msig[ 1] == 'C' &&
  1001.     myS3M->s3msig[ 2] == 'R' &&
  1002.     myS3M->s3msig[ 3] == 'M') return   noErr;
  1003.     else return  MADFileNotSupportedByThisPlug;
  1004. }
  1005.  
  1006. OSErr main( OSType order, FSSpec *AlienFileFSSpec, MADPartition *MadFile, PPInfoRec *info, MADDriverSettings *init)
  1007. {
  1008.     OSErr    myErr;
  1009.     Ptr        AlienFile;
  1010.     short    vRefNum, iFileRefI;
  1011.     long        dirID, sndSize;
  1012.     
  1013. #ifndef powerc
  1014.     long    oldA4 = SetCurrentA4();             //this call is necessary for strings in 68k code resources
  1015. #endif
  1016.  
  1017.     HGetVol( 0L, &vRefNum, &dirID);
  1018.     HSetVol( 0L, AlienFileFSSpec->vRefNum, AlienFileFSSpec->parID);
  1019.  
  1020.     myErr = noErr;
  1021.  
  1022.     switch( order)
  1023.     {
  1024.         case 'EXPL':
  1025.             AlienFile = ConvertMad2S3M( MadFile, init);
  1026.             
  1027.             if( AlienFile != 0L)
  1028.             {
  1029.                 myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  1030.                 if( myErr == fnfErr)
  1031.                 {
  1032.                     myErr = Create( AlienFileFSSpec->name, 0, 'SNPL', 'S3M ');
  1033.                     myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  1034.                 }
  1035.                 
  1036.                 if( myErr == noErr)
  1037.                 {
  1038.                     FInfo    fndrInfo;
  1039.                 
  1040.                     sndSize = GetPtrSize( AlienFile);
  1041.                     myErr = SetEOF( iFileRefI, sndSize);
  1042.                     myErr = FSWrite( iFileRefI, &sndSize, AlienFile);
  1043.                     FSClose( iFileRefI);
  1044.                     
  1045.                     GetFInfo( AlienFileFSSpec->name, 0, &fndrInfo);
  1046.                     fndrInfo.fdCreator    = 'SNPL';
  1047.                     fndrInfo.fdType        = 'S3M ';
  1048.                     SetFInfo( AlienFileFSSpec->name, 0, &fndrInfo);
  1049.                 }
  1050.                 DisposPtr( AlienFile);    AlienFile = 0L;
  1051.             }
  1052.             else myErr = MADNeedMemory;
  1053.         break;
  1054.         
  1055.         case 'IMPL':
  1056.             myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  1057.             if( myErr == noErr)
  1058.             {
  1059.                 GetEOF( iFileRefI, &sndSize);
  1060.             
  1061.                 // ** MEMORY Test Start
  1062.                 AlienFile = MADNewPtr( sndSize * 2L, init);
  1063.                 if( AlienFile == 0L) myErr = MADNeedMemory;
  1064.                 // ** MEMORY Test End
  1065.                 
  1066.                 else
  1067.                 {
  1068.                     DisposPtr( AlienFile);
  1069.                     
  1070.                     AlienFile = MADNewPtr( sndSize, init);
  1071.                     if( AlienFile == 0L) myErr = MADNeedMemory;
  1072.                     else
  1073.                     {
  1074.                         myErr = FSRead( iFileRefI, &sndSize, AlienFile);
  1075.                         if( myErr == noErr)
  1076.                         {
  1077.                             myErr = TestS3MFile( AlienFile);
  1078.                             if( myErr == noErr)
  1079.                             {
  1080.                                 myErr = ConvertS3M2Mad( AlienFile,  GetPtrSize( AlienFile), MadFile, init);
  1081.                             }
  1082.                         }
  1083.                     }
  1084.                     DisposPtr( AlienFile);    AlienFile = 0L;
  1085.                 }
  1086.                 FSClose( iFileRefI);
  1087.             }
  1088.         break;
  1089.         
  1090.         case 'TEST':
  1091.             myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  1092.             if( myErr == noErr)
  1093.             {
  1094.                 sndSize = 1024L;
  1095.                 
  1096.                 AlienFile = MADNewPtr( sndSize, init);
  1097.                 if( AlienFile == 0L) myErr = MADNeedMemory;
  1098.                 else
  1099.                 {
  1100.                     myErr = FSRead( iFileRefI, &sndSize, AlienFile);
  1101.                     myErr = TestS3MFile( AlienFile);
  1102.                     
  1103.                     DisposPtr( AlienFile);    AlienFile = 0L;
  1104.                 }
  1105.                 FSClose( iFileRefI);
  1106.             }
  1107.         break;
  1108.  
  1109.         case 'INFO':
  1110.             myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
  1111.             if( myErr == noErr)
  1112.             {
  1113.                 GetEOF( iFileRefI, &info->fileSize);
  1114.             
  1115.                 sndSize = 5000L;    // Read only 5000 first bytes for optimisation
  1116.                 
  1117.                 AlienFile = MADNewPtr( sndSize, init);
  1118.                 if( AlienFile == 0L) myErr = MADNeedMemory;
  1119.                 else
  1120.                 {
  1121.                     myErr = FSRead( iFileRefI, &sndSize, AlienFile);
  1122.                     if( myErr == noErr)
  1123.                     {
  1124.                         myErr = ExtractS3MInfo( info, AlienFile);
  1125.                     }
  1126.                     DisposPtr( AlienFile);    AlienFile = 0L;
  1127.                 }
  1128.                 FSClose( iFileRefI);
  1129.             }
  1130.         break;
  1131.         
  1132.         default:
  1133.             myErr = MADOrderNotImplemented;
  1134.         break;
  1135.     }
  1136.  
  1137.     HSetVol( 0L, vRefNum, dirID);
  1138.  
  1139.     #ifndef powerc
  1140.         SetA4( oldA4);
  1141.     #endif
  1142.     return myErr;
  1143. }